/*
	可复用测试client svr.
	acc_driver.h 每个功能的大概跑一遍。
	某些特殊例子不包含。
*/
#pragma once
#include <string>
#include <array>
#include "typedef.h"
#include "../acc_driver/include/acc_driver.h"

class BaseFunTestMgr;
static  const uint16 BF_SVR1 = 1;
static  const uint16 BF_SVR2 = 2;
static  const uint16 BF_SVR3 = 3;



class BaseClient : public lc::ClientCon
{
public:
	void SendStr(uint32 cmd, const std::string &msg);

	virtual void OnRecv(const lc::MsgPack &msg) override;
	virtual void OnRecvMsg(uint32 cmd, const std::string &msg) {};
	virtual void OnConnected() {};
	virtual void OnDisconnected() {};
};

class BaseFlowClient : public BaseClient
{
public:
	enum class State
	{
		WAIT_SVR_REG,
		WAIT_VERFIY_RSP,
		WAIT_SVR_RSP,
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;

public:
	BaseFlowClient(BaseFunTestMgr &mgr);
	virtual void OnRecv(const lc::MsgPack &msg) override final;
	virtual void OnRecvMsg(uint32 cmd, const std::string &msg) {};
	virtual void OnConnected() override final;
	virtual void OnDisconnected() override final;

	void SendVerify();
};


class BaseFlowSvr : public proto::IADFacade
{
public:
	enum class State
	{
		WAIT_SVR_REG,
		WAIT_CLIENT_REQ_VERFIY,
		WAIT_CLIENT_MSG,
		WAIT_CLIENT_DISCON,
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;

public:
	BaseFlowSvr(BaseFunTestMgr &mgr);

	//回调注册结果, 失败就是配置错误了，无法修复。重启进程吧。
	//@svrId = 0表示失败
	virtual void OnRegOK(uint32_t svrId) override;

	//接收client消息包.请求认证的包
	virtual void OnRevVerifyReq(const proto::SessionId& id, uint32 cmd, const std::string& msg) override;
	//接收client消息包到svr
	virtual void OnRevClientMsg(const proto::Session &session, uint32 cmd, const std::string &msg) override;

	//client断线通知
	virtual void OnClientDisCon(const proto::Session &sn) override;

};


class HeartBeatClient : public BaseClient
{
public:
	enum class State
	{
		WAIT_VERFIY_RSP, //send verify req, wait rsp
		WAIT_BEAT_RSP,//send heartbeat, wait rsp heartbeat
		WAIT_DISCONNECTED,//stop send heartbeat, wait acc disconnect.
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;

public:
	HeartBeatClient(BaseFunTestMgr &mgr);
	virtual void OnRecvMsg(uint32 cmd, const std::string &msg) override final;
	virtual void OnConnected() override final;
	virtual void OnDisconnected() override final;
};

// svr连接对象还是复用 BaseFlowSvr创建的
class HeartBeatSvr : public proto::IADFacade
{
public:
	enum class State
	{
		WAIT_VERFIY_REQ, 
		WAIT_CLIENT_BEAT_TIME_OUT, //set beathear info , start client connect, wait client beat
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;

public:
	HeartBeatSvr(BaseFunTestMgr &mgr);
	void Start();
	//回调注册结果, 失败就是配置错误了，无法修复。重启进程吧。
	//@svrId = 0表示失败
	virtual void OnRegOK(uint32_t svrId);

	//接收client消息包到svr
	virtual void OnRevClientMsg(const proto::Session &session, uint32 cmd, const std::string &msg);

	//接收client消息包.请求认证的包
	virtual void OnRevVerifyReq(const proto::SessionId &id, uint32 cmd, const std::string &msg);

	//client断线通知
	virtual void OnClientDisCon(const proto::Session &id) override;


};



//RUN_BROADCAST_DISCON client
class BDClient : public BaseClient
{
public:
	enum class State
	{
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;
	uint32 m_id; //id,0开始，数组索引

public:
	BDClient(BaseFunTestMgr &mgr);
	virtual void OnRecvMsg(uint32 cmd, const std::string &msg) override final;
	virtual void OnConnected() override final;
	virtual void OnDisconnected() override final;
};

//RUN_BROADCAST_DISCON svr
class BDSvr : public proto::IADFacade
{
public:
	enum class State
	{
		WAIT_ALL_CLIENT_CONNECT, //
		WAIT_ALL_VERIFY_OK,
		WAIT_BROADCAST, //broadcast all, broadcast one client,
		WAIT_DISCON_ONE,//discon one client
		WAIT_DISCON_ALL, //, discon all client.
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;
	std::set<uint64> m_client_set; //统计client集合
	std::set<proto::SessionId> m_clientSn_set; //统计client集合
	uint32 m_broadCmd_cnt;
	uint32 m_broadpartCmd_cnt;
	proto::SessionId m_anyone_sid;
	uint32 m_tmp_num;
public:
	BDSvr(BaseFunTestMgr &mgr);
	void Start();
	void ClientOnConnected(uint32 idx);
	void ClientRevBroadCmd();
	void ClientRevBroadPartCmd();
	void CheckBroadEnd();
	//回调注册结果, 失败就是配置错误了，无法修复。重启进程吧。
	//@svrId = 0表示失败
	virtual void OnRegOK(uint32_t svrId);

	//接收client消息包到svr
	virtual void OnRevClientMsg(const proto::Session &session, uint32 cmd, const std::string &msg) override;

	//接收client消息包.请求认证的包
	virtual void OnRevVerifyReq(const proto::SessionId &id, uint32 cmd, const std::string &msg) override;


	//client断线通知
	virtual void OnClientDisCon(const proto::Session& sn) override ;
};

//RUN_ROUTE
class RouteClient : public BaseClient
{
public:
	enum class State
	{
		WAIT_VERIFY_OK,
		WAIT_NORMAL_MSG_REV,//send svr1 svr2 msg, wait rev
		WAIT_CHANGE_ROUTE_MSG_REV, //change route msg, send svr3 msg to svr2. wait rev
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state;
	uint32 m_tmp1;
	uint32 m_tmp2;
	lc::Timer m_tm;
	proto::SessionId m_snId; //svr1 回合id
public:
	RouteClient(BaseFunTestMgr &mgr);
	void Start();
	virtual void OnRecvMsg(uint32 cmd, const std::string &msg) override final;
	virtual void OnConnected() override final;
	virtual void OnDisconnected() override final {};
};

//RUN_ROUTE
class RouteSvr : public proto::IADFacade
{
public:
	enum class State
	{
		START,
		WAIT_ROUE_MSG_TO_SVR2,
		END,
	};

	BaseFunTestMgr &m_mgr;
	State m_state = State::START;
	uint16 m_svr_id = 0;
	proto::SessionId m_sid;
	bool m_isCreateSn = false;
public:
	RouteSvr(BaseFunTestMgr &mgr);


	//回调注册结果, 失败就是配置错误了，无法修复。重启进程吧。
	//@svrId = 0表示失败
	virtual void OnRegOK(uint32_t svrId);

	//接收client消息包到svr
	virtual void OnRevClientMsg(const proto::Session &session, uint32 cmd, const std::string &msg);

	//接收client消息包.请求认证的包
	virtual void OnRevVerifyReq(const proto::SessionId &id, uint32 cmd, const std::string &msg);

	//client断线通知
	virtual void OnClientDisCon(const proto::Session& id) override {};

};





//基本功能，流程测试
class BaseFunTestMgr 
{
public:
	enum class State
	{
		RUN_NONE,
		RUN_HEARTBEAT,
		RUN_BROADCAST_DISCON, //测试广播，踢人
		RUN_ROUTE,//路由设置
		RUN_BROADCAST_UIN,
		END,
	};

	//step 1  RUN_CORRECT_FOLLOW
	BaseFlowClient m_client;
	BaseFlowSvr m_svr; 

	//step 2 心跳测试
	HeartBeatClient m_h_client;
	HeartBeatSvr m_hSvr;

	//step3 broad cast dicon client
	std::array<BDClient,3> m_bd_client;
	BDSvr m_bd_svr;

	//step4 test route
	RouteSvr m_route_svr1;
	RouteSvr m_route_svr2;
	RouteClient m_route_client;

	State m_state;
	lc::Timer m_tm;
	lc::Timer m_endtm;

public:
	BaseFunTestMgr();
	bool Init();
	void StartHeartbeatTest();
	void StartCheckBD();//TEST RUN_BROADCAST_DISCON
	void StartCheckRoute();//TEST RUN_ROUTE

};
